/*
Copyright 2010 SGSL

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package com.dataiti.sgsl;

import java.awt.BorderLayout;
import java.awt.Color;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.BorderFactory;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import com.dataiti.sgsl.globe.SGSLGlobe;
import com.dataiti.sgsl.layer.SGSL;

public abstract class SGSLApplet extends JApplet implements ComponentListener, ISGSL {
	
   
	private static final long serialVersionUID = 1L; // silence warning
    
	/**
	 * ObjGlobe holds the Globe object of type SGSLGlobe
	 */
	private SGSLGlobe objGlobe = null;
    
	/**
	 * objsgsl is the library to do operations on the globe
	 */
	private SGSL objsgsl = null;
    
	/**
	 * CurrentWidth holds the width of the component Container
	 */
	private int currentWidth;
    
	/**
	 * CurrentWidth holds the height of the component Container
	 */
	private int currentHeight;
	
	/**
	 * initResize flag determines globe resize event
	 */
	private boolean initResize = true;
	/**
	 * ctrl holds the Applet GUI controls
	 */
	private AppletControls ctrl = null;
	
	
	/**
	 * display arc of great circle connecting two points.
	 * 
	 * @param startLat
	 * @param startLon
	 * @param endLat
	 * @param endLon
	 */
	public void drawArc(double startLat, double startLon, double endLat,
			double endLon) {
		objsgsl.drawArc(startLat, startLon, endLat, endLon);
	}

    /**
     * 
     */
	public void drawArc(double angle, double length) {
		objsgsl.drawArc(angle, length);
	}

    
	/**
	 * display empty circle centered at current position
	 * 
	 * @param radius
	 */
	public void drawCircle(double radius) {
		objsgsl.drawCircle(radius);
	}

	
	/**
	 * display string as a label at current position on the illustration (First
	 * character displays 2 millimeteres to the right of the position to avoid
	 * being right on top of the position.)
	 * 
	 * @param string
	 */
	public void drawLabel(String string) {
		objsgsl.drawLabel(string);
	}

	
	/**
	 * display a point(circle) centered at current position
	 * 
	 * @param radius
	 */
	public void drawPoint() {
		objsgsl.drawPoint();
	}

   
	/**
	 * Checks for the object reference equality
	 */
	public boolean equals(Object obj) {
		return objsgsl.equals(obj);
	}

    /**
	  * Erases the entire graphics and its associated object like circle,line,point,arc
	*/
	public void eraseGraphic() {
		objsgsl.eraseGraphic();
	}

    /**
     * Returns the globe object
     * @return globe of type SGSLGLobe
     */
	public SGSLGlobe getGlobe() {
		return objsgsl.getGlobe();
	}

    /**
     * returns hashCode of this applet object
     */
	public int hashCode() {
		return objsgsl.hashCode();
	}

	
	  /**
	 * print a message on the lower panel of the applet. On screen - grows a
	 * scroll bar if there are lots of messages. Font and size are as would be
	 * created by default by System.out.println().
	 * 
	 * @param string
	 */
	public void printMessage(String string) {
		objsgsl.printMessage(string);
	}

    
	/**
	 * print applet on paper. The usual platform-dependent print dialog should
	 * help select the printer which can be any kind of printing device
	 * supporting standard paper sizes (US Letter required at minimum). There
	 * should be nothing stopping the user from printing to a PDF writer so they
	 * get a file they can easily save, email as an attachment, etc. The print
	 * out would include the graphic illustration, and the message panel below
	 * it, continuing on additional pages to fit all messages.
	 */
	public void printPage() {
		objsgsl.printPage();
	}

	
	/**
	 * displays the continent & country boundary map.
	 * @param visible - Boolean flag to set on/off
	 */
	public void setBackground(boolean visible) {
		objsgsl.setBackground(visible);
	}

    
	/**
	 * illustration is centered at this lat and lon. North pole is always top
	 * center if not on the graphic, and on a vertical centerline of the graphic
	 * if it appears on the graphic.
	 * 
	 * @param lat
	 * @param lon
	 */
	public void setCenter(double lat, double lon) {
		objsgsl.setCenter(lat, lon);
	}
    
	
	/**
	 * change current color. Color code is an instance of an enum void Color
	 * having values specified below. Applies to both text and lines.
	 * 
	 * @param color
	 */
	public void setColor(Color color) {
		objsgsl.setColor(color);
	}
   
	
	
	/**
	 * set current drawing position to lat and lon
	 * 
	 * @param lat
	 * @param lon
	 */
	public void setDrawingPosition(double lat, double lon) {
		objsgsl.setDrawingPosition(lat, lon);
	}

    
	/**
	 * displays the grid lines of the projection
	 * @param visible - Boolean flag to set on/off
	 */
	public void setGridLines(boolean visible) {
		objsgsl.setGridLines(visible);
	}
    
	
	
	/**
	 * sets size of text displayed on illustration. This is NOT a font size. It is
	 * measured as a fraction of the graphical panel size. Example 0.05 means
	 * the letters are about 5% of the height of the entire graphical panel.The maximum
	 * textHeightFraction is limited to 0.10.
	 * 
	 * @param textHeightFraction
	 */
	public void setLabelSize(double textHeightFraction) {
		objsgsl.setLabelSize(textHeightFraction);
	}

    
	/**
	 * Width and height of illustration (that is, it is zoomed to show this much
	 * of the earth).
	 * 
	 * @param sz
	 *            The width and height are both given by this single parameter
	 *            in decimal degrees.
	 */
	
	public void setWidthAndHeight(double sz) {
		objsgsl.setWidthAndHeight(sz);
	}
	
	
	/**
	 * display filled circle centered at current position
	 * 
	 * @param radius
	 */
	public void drawFilledCircle(double radius) {
		objsgsl.drawFilledCircle(radius);
		
	}
   
	
	protected void setColor (double colorNum) {
		int colorIndex;
		colorIndex = (int) (colorNum % 10); // exclude white (which is color 11)
		
		switch (colorIndex) {

		case 0: setColor(black); break;
		case 1: setColor(blue); break;
		case 2: setColor(darkGray); break;
		case 3: setColor(gray); break;
		case 4: setColor(green); break;
		case 5: setColor(lightGray); break;
		case 6: setColor(magenta); break;
		case 7: setColor(orange); break;
		case 8: setColor(pink); break;
		case 9: setColor(red); break;
		case 10: setColor(yellow); break;
		case 11: setColor(white); break;

		}
	}
		
    /**
     * Returns string representation of the applet object
     */
	public String toString() {
		return objsgsl.toString();
	}
    

     /**
      * 
      *Constructor to build Applet and its controls
      */
	public SGSLApplet() {
		
		objsgsl = SGSL.create();
	
		// should be at last always
		objGlobe = objsgsl.getGlobe();
		getContentPane().add(objGlobe);
			
	}
	
/**
 * This method will initalize all applet controls
 *
 */
   protected void initControls()
   {
 	 ctrl = new AppletControls(objsgsl);

	 // adding controls
	 getContentPane().add(ctrl, BorderLayout.SOUTH);
	 getContentPane().setBackground(Color.WHITE);
	 addComponentListener(this);
   }

	
/**
 * This class build appletcontrols
 * 
 *
 */
	private static class AppletControls extends JPanel implements ActionListener {

		private static final long serialVersionUID = 1L; // silence warning

		private JButton cmdPrint;

		private JTextArea txtLabel;
		private JScrollPane scrlPane;
		SGSL objSGSL;

		public AppletControls(SGSL objSGSL) {

			add(txtLabel = new JTextArea());

			txtLabel.setBorder(BorderFactory.createEtchedBorder());
			txtLabel.setText(objSGSL.getGlobe().getPrintLabel());
			txtLabel.setLineWrap(true);
			txtLabel.setWrapStyleWord(true);

			scrlPane = new JScrollPane(txtLabel);
			scrlPane.setPreferredSize(new Dimension(700, 100));
			scrlPane.setAutoscrolls(true);

			add(scrlPane);

			// add(cmdPrint = new JButton("Print"),BorderLayout.SOUTH);
			add(cmdPrint = new JButton("Print"));
			cmdPrint.addActionListener(this);
			this.objSGSL = objSGSL;			
		}

		public void actionPerformed(ActionEvent e) {
			Object o = e.getSource();
			if (o == cmdPrint) {
				objSGSL.printMessage(txtLabel.getText());
				objSGSL.printPage();
			
			}
		}


	}
    
	
	/**
	 * This method can be overrided when the coponentHidden event execution is needed
	 */
	public void componentHidden(ComponentEvent event) {
		

	}
    
	
	/**
	 * This method can be overrided when the coponentMoved event execution is needed
	 */
	public void componentMoved(ComponentEvent event) {
		

	}

	
	/**
	 * This method is overrided to resize the globe when component resize event occurs
	 */
	public void componentResized(ComponentEvent event) {

		if (initResize != true) {
			objGlobe.getMap().getTransform().scale(
					1 + (getWidth() - currentWidth) * 0.002,
					1 + (getHeight() - currentHeight) * 0.002);			
			
			currentWidth = getWidth();
			currentHeight = getHeight();
			
		}
	
	}
    
	
	/**
	 * This method can be overrided when the coponentShown event execution is needed
	 */
	public void componentShown(ComponentEvent event) {	

	}
    
	
	/**
	 * This method will be executes when the applet starts
	 */
	public void start() {
		super.start();
		initResize = false;
		currentWidth = getWidth();
		currentHeight = getHeight();
		draw();
		initControls();

	}
    
	
	/**
	 *Implement this method to draw a globe and other objects on the globe like
	 *circle,arc,line
	 */
	protected abstract void draw();

   /**
    * This method will get executed when the applet initialize
    */
	public void init() {
		super.init();
		setSize(new Dimension(945, 587));
	}
	


}
